package com.wolfeyes.framework.web.serializer;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import lombok.extern.slf4j.Slf4j;
import com.wolfeyes.framework.web.serializer.enums.BaseEnum;
import com.wolfeyes.framework.web.serializer.exception.DictDeserializerException;

import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;

/**
 * @title 字符串（数据库的字典字段code）转翻译字典的反序列化器
 * @className StringAsDictDeserializer
 * @author yanyljava
 * @create 2022-01-14 21:25
 */
@Slf4j
@JacksonStdImpl
public class StringAsDictDeserializer extends JsonDeserializer<BaseEnum> implements ContextualDeserializer {

	/**
	 * @title 枚举类Enum的字节码对象
	 */
	private Class<?> typeClazz;

	public StringAsDictDeserializer(Class<?> typeClazz) {
		this.typeClazz = typeClazz;
	}
	
	/**
	 * @title 空构造方法
	 */
	public StringAsDictDeserializer() {
		
	}

	/**
	 * @title 反序列化操作
	 * @title 数据库字典字段code回显前端字典枚举值的自动反序列化转换逻辑
	 * @return 数据库字典字段code所对应的字典类型枚举值
	 */
	@Override
	public BaseEnum deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
		// 等价于数据库的字典字段code值
		String value = jsonParser.getValueAsString();
		// 通过当前数据库字典字段code值获取字典类型Enum
		BaseEnum typeEnum = Arrays.stream(this.typeClazz.getEnumConstants()).map(t -> (BaseEnum) t)
				.filter(t -> Objects.equals(t.getCode(), value))
				.findAny().orElse(null);
		if(typeEnum == null) {
			
			throw new DictDeserializerException("value is error, not found enum type");
		}
		
		return typeEnum;
	}

	@Override
	public JsonDeserializer<?> createContextual(DeserializationContext deserializationContext, BeanProperty beanProperty) throws JsonMappingException {
		// 实现ContextualSerializer接口，从BeanProperty属性中获取反序列化属性（字典枚举值）所对应的字典类型枚举类Enum的字节码对象信息
		Class<?> typeClazz = beanProperty.getType().getRawClass();
		return new StringAsDictDeserializer(typeClazz);
	}
}
